#include "stdafx.h"
#include "net/HTTPMessage.hpp"
#include "net/MediaType.hpp"
#include "utils/numberformatter.hpp"
#include "utils/numberparser.hpp"
using JHCPP::utils::CNumberFormatter;
using JHCPP::utils::CNumberParser;
#include "charset/string.hpp"
using JHCPP::charset::icompare;

NET_NAMESPACE_BEGIN

const std::string CHTTPMessage::HTTP_1_0                   = "HTTP/1.0";
const std::string CHTTPMessage::HTTP_1_1                   = "HTTP/1.1";
const std::string CHTTPMessage::IDENTITY_TRANSFER_ENCODING = "identity";
const std::string CHTTPMessage::CHUNKED_TRANSFER_ENCODING  = "chunked";
const int         CHTTPMessage::UNKNOWN_CONTENT_LENGTH     = -1;
const std::string CHTTPMessage::UNKNOWN_CONTENT_TYPE;
const std::string CHTTPMessage::CONTENT_LENGTH             = "Content-Length";
const std::string CHTTPMessage::CONTENT_TYPE               = "Content-Type";
const std::string CHTTPMessage::TRANSFER_ENCODING          = "Transfer-Encoding";
const std::string CHTTPMessage::CONNECTION                 = "Connection";
const std::string CHTTPMessage::CONNECTION_KEEP_ALIVE      = "Keep-Alive";
const std::string CHTTPMessage::CONNECTION_CLOSE           = "Close";
const std::string CHTTPMessage::EMPTY;

CHTTPMessage::CHTTPMessage() : m_version(HTTP_1_0)
{
}

CHTTPMessage::CHTTPMessage(const std::string& version) : m_version(version)
{
}

CHTTPMessage::~CHTTPMessage()
{
}

void CHTTPMessage::setVersion(const std::string& version)
{
	m_version = version;
}

const std::string& CHTTPMessage::getVersion() const
{
	return m_version;
}

void CHTTPMessage::setContentLength(std::streamsize length)
{
	if (length != UNKNOWN_CONTENT_LENGTH)
		set(CONTENT_LENGTH, CNumberFormatter::format(length));
	else
		erase(CONTENT_LENGTH);
}

std::streamsize CHTTPMessage::getContentLength() const
{
	const std::string& contentLength = get(CONTENT_LENGTH, EMPTY);
	if (!contentLength.empty())
	{
		if (sizeof(std::streamsize) == sizeof(Int64))
			return static_cast<std::streamsize>(CNumberParser::parse64(contentLength));
		else
			return static_cast<std::streamsize>(CNumberParser::parse(contentLength));
	}
	else 
		return UNKNOWN_CONTENT_LENGTH;
}

#if defined(JH_HAVE_INT64)	
void CHTTPMessage::setContentLength64(Int64 length)
{
	if (length != UNKNOWN_CONTENT_LENGTH)
		set(CONTENT_LENGTH, CNumberFormatter::format(length));
	else
		erase(CONTENT_LENGTH);
}

Int64 CHTTPMessage::getContentLength64() const
{
	const std::string& contentLength = get(CONTENT_LENGTH, EMPTY);
	if (!contentLength.empty())
	{
		return CNumberParser::parse64(contentLength);
	}
	else 
		return UNKNOWN_CONTENT_LENGTH;
}
#endif

bool CHTTPMessage::hasContentLength() const
{
	return has(CONTENT_LENGTH);
}

void CHTTPMessage::setTransferEncoding(const std::string& transferEncoding)
{
	if (icompare(transferEncoding, IDENTITY_TRANSFER_ENCODING) == 0)
		erase(TRANSFER_ENCODING);
	else
		set(TRANSFER_ENCODING, transferEncoding);
}

const std::string& CHTTPMessage::getTransferEncoding() const
{
	return get(TRANSFER_ENCODING, IDENTITY_TRANSFER_ENCODING);
}

void CHTTPMessage::setChunkedTransferEncoding(bool flag)
{
	if (flag)
		setTransferEncoding(CHUNKED_TRANSFER_ENCODING);
	else
		setTransferEncoding(IDENTITY_TRANSFER_ENCODING);
}

bool CHTTPMessage::getChunkedTransferEncoding() const
{
	return icompare(getTransferEncoding(), CHUNKED_TRANSFER_ENCODING) == 0;
}

void CHTTPMessage::setContentType(const std::string& mediaType)
{
	if (mediaType.empty())
		erase(CONTENT_TYPE);
	else
		set(CONTENT_TYPE, mediaType);
}

void CHTTPMessage::setContentType(const CMediaType& mediaType)
{
	setContentType(mediaType.toString());
}

const std::string& CHTTPMessage::getContentType() const
{
	return get(CONTENT_TYPE, UNKNOWN_CONTENT_TYPE);
}

void CHTTPMessage::setKeepAlive(bool keepAlive)
{
	if (keepAlive)
		set(CONNECTION, CONNECTION_KEEP_ALIVE);
	else
		set(CONNECTION, CONNECTION_CLOSE);
}

bool CHTTPMessage::getKeepAlive() const
{
	const std::string& connection = get(CONNECTION, EMPTY);
	if (!connection.empty())
		return icompare(connection, CONNECTION_CLOSE) != 0;
	else
		return getVersion() == HTTP_1_1;
}

NET_NAMESPACE_END
